﻿Imports Runa.Common.Helper
Imports System.Runtime.InteropServices

Namespace Global.System.Reflection

    Public Module Extension

#If NETFX_CORE Then

        <Extension()> _
        Public Function Assembly(ByVal [Me] As Type) As Assembly
            Return [Me].GetTypeInfo().Assembly
        End Function

        <Extension()>
        Public Sub ForEachProperty(ByVal t As Type, ByVal Check As Action(Of PropertyInfo))
            Dim ps = t.GetRuntimeProperties()
            For Each p In ps
                Check(p)
            Next
        End Sub

        <Extension()>
        Public Sub SetValueEx(ByVal p As PropertyInfo, ByVal obj As Object, ByVal value As Object, ByVal oldValue As Object)
            Try
                If p.PropertyType Is GetType(Integer) Then
                    p.SetValue(obj, GenericCast(Of String, Integer)(value))
                ElseIf p.PropertyType Is GetType(Boolean) Then
                    p.SetValue(obj, GenericCast(Of String, Boolean)(value))
                ElseIf p.PropertyType Is GetType(String) Then
                    p.SetValue(obj, value.ToString())
                Else
                    Throw New NotSupportedException("Not supported property type.")
                End If
            Catch ex As Exception
                p.SetValue(obj, oldValue)
            End Try
        End Sub

        <Extension()>
        Public Sub SetValueEx(ByVal p As PropertyInfo, ByVal obj As Object, ByVal value As Object, ByVal oldValue As Object, ByVal converter As Func(Of Object, Object))
            Try
                p.SetValue(obj, converter(value))
            Catch ex As Exception
                p.SetValue(obj, oldValue)
            End Try
        End Sub

#Else

        <Extension()> _
        Public Function GetField(Of T)(ByVal [Me] As Object, ByVal eventName As String) As T
            Dim fi As FieldInfo = [Me].GetType().GetField(eventName, BindingFlags.Instance Or BindingFlags.NonPublic)
            Return fi.GetValue([Me])
        End Function

        <Extension()>
        Public Function ExportedTypes(ByVal [Me] As Assembly) As Type()
            Return [Me].GetExportedTypes()
        End Function

        <Extension()>
        Public Function GetGUID(ByVal asm As Assembly) As Guid
            Dim attr As GuidAttribute = Attribute.GetCustomAttribute(asm, GetType(GuidAttribute))
            Return New Guid(attr.Value)
        End Function

        <Extension()>
        Public Sub SetValue(ByVal p As PropertyInfo, ByVal obj As Object, ByVal value As Object)
            p.SetValue(obj, value, Nothing)
        End Sub

        <Extension()>
        Public Sub SetValueEx(ByVal p As PropertyInfo, ByVal obj As Object, ByVal value As Object, ByVal oldValue As Object)
            Try
                If p.PropertyType Is GetType(Integer) Then
                    p.SetValue(obj, GenericCast(Of String, Integer)(value), Nothing)
                ElseIf p.PropertyType Is GetType(Boolean) Then
                    p.SetValue(obj, GenericCast(Of String, Boolean)(value), Nothing)
                ElseIf p.PropertyType Is GetType(String) Then
                    p.SetValue(obj, value.ToString(), Nothing)
                Else
                    Throw New NotSupportedException("Not supported property type.")
                End If
            Catch ex As Exception
                p.SetValue(obj, oldValue, Nothing)
            End Try
        End Sub

        <Extension()>
        Public Sub SetValueEx(ByVal p As PropertyInfo, ByVal obj As Object, ByVal value As Object, ByVal oldValue As Object, ByVal converter As Func(Of Object, Object))
            Try
                p.SetValue(obj, converter(value), Nothing)
            Catch ex As Exception
                p.SetValue(obj, oldValue, Nothing)
            End Try
        End Sub

#End If

    End Module

End Namespace